package com.demarc.pesquisas.negocio.util;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.Locale;

import org.apache.commons.lang3.StringUtils;

public final class NumberUtils {

	public static final Locale LOCALE_PT_BR = new Locale("pt", "br");
	public static final int SCALE = 2;

	private NumberUtils() {
	}

	/**
	 * Recebe um valor BigDecimal e formata para String.
	 * 
	 * @param valor
	 *            valor em BigDecimal.
	 * 
	 * @return o BigDecimal representado em String.<br>
	 *         Se o valor passado como parâmetro for nulo, este método retorna
	 *         um objeto nulo.
	 */
	public static String converterParaString(Number valor,
			boolean exibirApenasDecimaisAcimaDeZero) {
		DecimalFormat formatador = getFormatadorDeNumeros();
		formatador.applyPattern(getPadraoString(SCALE,
				exibirApenasDecimaisAcimaDeZero));
		if (valor != null) {
			return formatador.format(valor);
		}
		return null;
	}

	public static String converterParaString(Number valor) {
		return converterParaString(valor, false);
	}

	public static DecimalFormat getFormatadorDeNumeros() {
		return (DecimalFormat) DecimalFormat.getInstance(LOCALE_PT_BR);
	}

	/**
	 * Retorna o padrão de representação para um BigDecimal de acordo com a
	 * quantidade de casas decimais passada.
	 * 
	 * @param decimais
	 *            Quantidade de casas decimais.
	 * 
	 * @param exibirApenasDecimaisAcimaDeZero
	 *            Se a casa decimal for zero, não exibe as casas decimais.
	 * 
	 * @return o padrão para a formatação de um BigDecimal.
	 */
	public static String getPadraoString(int decimais,
			boolean exibirApenasDecimaisAcimaDeZero) {

		StringBuilder padraoBuilder = new StringBuilder("##,##0");
		if (decimais > 0) {
			padraoBuilder.append(".");
		}

		String decimal = exibirApenasDecimaisAcimaDeZero ? "#" : "0";
		for (int i = 0; i < decimais; i++) {
			padraoBuilder.append(decimal);
		}

		return padraoBuilder.toString();
	}

	/**
	 * Converte uma String em um valor BigDecimal.
	 * 
	 * @param value
	 *            valor em String.
	 * 
	 * @return a String representada em um BigDecimal.
	 * @throws ParseException
	 */
	public static BigDecimal converterDeStringParaBigDecimal(String value)
			throws ParseException {
		BigDecimal bigDecimal = null;

		if (StringUtils.isNotBlank(value)) {
			DecimalFormat formatter = getFormatadorDeNumeros();
			formatter.applyPattern(getStringPattern(SCALE));

			Number number = formatter.parse(value.trim().replace(',',
					formatter.getDecimalFormatSymbols().getDecimalSeparator()));
			bigDecimal = BigDecimal.valueOf(number.doubleValue()).setScale(
					SCALE, RoundingMode.HALF_DOWN);
		}

		return bigDecimal;
	}

	public static String convertToString(Number value) {
		return convertToString(value, false);
	}

	/**
	 * Recebe um valor BigDecimal e formata para String.
	 * 
	 * @param value
	 *            valor em BigDecimal.
	 * 
	 * @return o BigDecimal representado em String.<br>
	 *         Se o valor passado como parâmetro for nulo, este método retorna
	 *         um objeto nulo.
	 */
	public static String convertToString(Number value,
			boolean exibirApenasDecimaisAcimaDeZero) {
		String stringValue = null;
		DecimalFormat formatter = getFormatadorDeNumeros();
		formatter.applyPattern(getStringPattern(SCALE,
				exibirApenasDecimaisAcimaDeZero));

		if (value != null) {
			stringValue = formatter.format(value);
		}

		return stringValue;
	}

	/**
	 * Retorna o padrão de representação para um BigDecimal de acordo com a
	 * quantidade de casas decimais passada.
	 * 
	 * @param decimals
	 *            Quantidade de casas decimais.
	 * 
	 * @param exibirApenasDecimaisAcimaDeZero
	 *            Se a casa decimal for zero, não exibe as casas decimais.
	 * 
	 * @return o padrão para a formatação de um BigDecimal.
	 */
	public static String getStringPattern(int decimals,
			boolean exibirApenasDecimaisAcimaDeZero) {

		StringBuilder sb = new StringBuilder("##,##0");
		if (decimals > 0) {
			sb.append(".");
		}

		String decimal = exibirApenasDecimaisAcimaDeZero ? "#" : "0";
		for (int i = 0; i < decimals; i++) {
			sb.append(decimal);
		}

		return sb.toString();
	}

	public static String getStringPattern(int decimals) {
		return getPadraoString(decimals, false);
	}
}
